import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.ImageIcon;
import clientAPI.*;

// 
/**
 * ServerListener (and serverSender)
 * @author Torbjorn Elebjork							
 */
public class ServerListener extends Thread {
	Boolean run;
	Socket requestSocket;
	ObjectOutputStream out;
	ObjectInputStream in;
 	ServerMessage recServerMessage;
 	GUIMain guiMain;
 	MapGraphics guiRun;
 	Map map;
 	ImageIcon imageIcon;
 	
	/**
	 * The constructor creates a socket.
	 * @param ip The ip-address to the server
	 * @param port The port the socket communication through
	 */
	ServerListener(String ip, int port,GUIMain guiMain, MapGraphics guiRun, Map map){
		this.guiMain = guiMain;
		this.guiRun = guiRun;
		this.map = map;
		run=true;
		try{
			requestSocket = new Socket(ip, port);
			System.out.println("ServerListener is connected to " + ip + " on port " + port);
		}
		catch(UnknownHostException unknownHost){
			System.err.println("Trying to connect to an unknown host.");
		}
		catch(IOException ioException){
			System.out.println("Could not create requestSocket: " + ioException );
			System.out.println("Print Stack Trace: ");
			ioException.printStackTrace();
		}	
	}
	
	/**
	 * Starts the ServerListener thread. 
	 * Listens to the server for messages that hold new information about the map, 
	 * updates the map and then repaint it.
	 */
	public void run(){
		try{
			out = new ObjectOutputStream(requestSocket.getOutputStream());
			out.flush();
			in = new ObjectInputStream(requestSocket.getInputStream());
			try{
				do{	// All communication to the GUI thread is be done here
					// 3 = Robot position, 2 = Occupied, 1 = free, 0 = Unknown
					recServerMessage = (ServerMessage)in.readObject();
					map.setStateAt(recServerMessage.getMapValueXPosition(),recServerMessage.getMapValueYPosition(),recServerMessage.getMapValue());	
					guiRun.repaint();	
					System.out.println("server> " + recServerMessage.toString());
					if(recServerMessage!=null ){
						System.out.println("server> " + recServerMessage.toString());
					}		
				} while(run);	 
			}
			catch(ClassNotFoundException classNot){
				System.err.println("Recieved data has invalid format.");
			}	
		}
		catch(IOException ioException){
			System.out.println("Could not create input/output streams:" + ioException );
			System.out.println("Print Stack Trace 2: ");
			ioException.printStackTrace();
		}
		finally{		//Closing connection
			try{
				guiMain.setCurrentServerIPTextbox("Disconnected");
				in.close();
				out.close();
				requestSocket.close();
				System.out.println("Socket successfully closed");
			}
			catch(IOException ioException){
				ioException.printStackTrace();
			}
		}
	}
	
	/**
	 * Sends a ClientMessage object to the server. (ClientMessage is defined in the clientAPI)
	 * @param clientMessage	(ClientMessage is defined in the clientAPI)
	 */
	void sendMessage(ClientMessage clientMessage)
	{
		try{
			out.writeObject(clientMessage);
			out.flush();
		}
		catch(IOException ioException){
			guiMain.setCurrentServerIPTextbox("Disconnected");
			ioException.printStackTrace();
		}
	}
	
	/**
	 * Terminates the thread
	 * @param setRun
	 */
	void setRun(Boolean setRun){
		run = setRun;
	}
}
